/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "esp8266.h"
#include "oled.h"
#include "stdio.h"
#include "string.h"
#include "dht11.h"
#include "semphr.h"
#include "bh1750.h"
#include "show.h"
#include "timers.h"
#include "upload.h"
#include "control.h"
#include "link.h"
#include "queue.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

extern UART_HandleTypeDef huart2;

EnvInfo gInfo = {.cur_time = 1718106353,};

xQueueHandle uartHandle;
SemaphoreHandle_t semHandle;
TimerHandle_t dataTimerHandle;
TimerHandle_t buzzerTimerHandle;

uint8_t gMenu = 1;
uint8_t gBuzzerFlag = 0;

uint8_t gUartBuf[256] = {0};

osThreadId_t receiveTaskHandle;
const osThreadAttr_t receiveTask_attributes = {
  .name = "receiveTask",
  .stack_size = 128 * 4 * 2,
  .priority = (osPriority_t) osPriorityNormal,
};

osThreadId_t tempTaskHandle;
const osThreadAttr_t tempTask_attributes = {
  .name = "tempTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};

osThreadId_t lightTaskHandle;
const osThreadAttr_t lightTask_attributes = {
  .name = "lightTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};

osThreadId_t OLEDTaskHandle;
const osThreadAttr_t OLEDTask_attributes = {
  .name = "OLEDTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal1,
};

osThreadId_t UploadTaskHandle;
const osThreadAttr_t UploadTask_attributes = {
  .name = "UploadTask",
  .stack_size = 128 * 4 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};


/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
  .name = "defaultTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

void ReceiveTask(void *arg);
void Task_Receive_Msg(uint8_t *m);
void GetTempTask(void *arg);
void GetLightTask(void *arg);
void OLED_Show_Task(void *arg);
uint8_t Key_Scan(void);
void Data_Increase_Callback(TimerHandle_t xTimer);
void UploadTask(void *arg);
void Buzzer_Callback(TimerHandle_t xTimer);

/* USER CODE END FunctionPrototypes */

void StartDefaultTask(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
	/* USER CODE BEGIN Init */

	/* USER CODE END Init */

	/* USER CODE BEGIN RTOS_MUTEX */
	/* add mutexes, ... */
	/* USER CODE END RTOS_MUTEX */

	/* USER CODE BEGIN RTOS_SEMAPHORES */
	/* add semaphores, ... */
	
	semHandle = xSemaphoreCreateBinary();
	xSemaphoreGive(semHandle);
	
	/* USER CODE END RTOS_SEMAPHORES */

	/* USER CODE BEGIN RTOS_TIMERS */
	/* start timers, add new ones, ... */
	int timeid = 1;
	dataTimerHandle = xTimerCreate("data", 1000, pdTRUE, &timeid, Data_Increase_Callback);
	
	int timeid2 = 2;
	buzzerTimerHandle = xTimerCreate("buzzer", 1, pdTRUE, &timeid2, Buzzer_Callback);
	/* USER CODE END RTOS_TIMERS */

	/* USER CODE BEGIN RTOS_QUEUES */
	/* add queues, ... */
	uartHandle = xQueueCreate(5, sizeof(gUartBuf));
	/* USER CODE END RTOS_QUEUES */

	/* Create the thread(s) */
	/* creation of defaultTask */
	defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

	/* USER CODE BEGIN RTOS_THREADS */
	/* add threads, ... */
	/* USER CODE END RTOS_THREADS */

	/* USER CODE BEGIN RTOS_EVENTS */
	/* add events, ... */
	/* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
	/* USER CODE BEGIN StartDefaultTask */
	/* Infinite loop */
	OLED_Init();
	OLED_Clear();
	
	OLED_ShowString(0, 0, (uint8_t *)"[1]START WORKING", 16);
	
	ESP8266_Init();
	
	if (ESP8266_Connect_AP(SSID, PASSWORD))
		OLED_ShowString(0, 2, (uint8_t *)"[2]CONN WIFI OK", 16);
	else
		OLED_ShowString(0, 2, (uint8_t *)"[2]CONN WIFI ERR", 16);
	
	if (ESP8266_Connect_MQTT(MQTTIP, MQTTPORT, "test", "test"))
		OLED_ShowString(0, 4, (uint8_t *)"[3]CONN MQTT OK", 16);
	else
		OLED_ShowString(0, 4, (uint8_t *)"[3]CONN MQTT ERR", 16);
	
	if (ESP8266_Subscribe(DEVICEID))
		OLED_ShowString(0, 6, (uint8_t *)"[4]MQTT SUB OK", 16);
	else 
		OLED_ShowString(0, 6, (uint8_t *)"[4]MQTT SUB ERR", 16);
	
	osDelay(1000);
	
	//start timer
	xTimerStart(dataTimerHandle, portMAX_DELAY);
	
	HAL_UARTEx_ReceiveToIdle_IT(&huart2, gUartBuf, sizeof(gUartBuf));
	
	//创建任务
	receiveTaskHandle = osThreadNew(ReceiveTask, NULL, &receiveTask_attributes);
	tempTaskHandle = osThreadNew(GetTempTask, NULL, &tempTask_attributes);
	lightTaskHandle = osThreadNew(GetLightTask, NULL, &lightTask_attributes);
	OLEDTaskHandle = osThreadNew(OLED_Show_Task, NULL, &OLEDTask_attributes);
	UploadTaskHandle = osThreadNew(UploadTask, NULL, &UploadTask_attributes);
	
	for(;;)
	{
		if (Key_Scan() == 1)
		{
			if (gBuzzerFlag == 1)
			{
				Control_Buzzer_Stop();
			}
			else
			{
				gMenu++;
				
				if (gMenu == 5)
					gMenu = 1;
			}
		}
		
		if (gBuzzerFlag == 0 && Link_Alarm_Isset())
		{
			Control_Buzzer_Start();
		}
		
		osDelay(50);
	}
	/* USER CODE END StartDefaultTask */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
void ReceiveTask(void *arg)
{
	uint8_t msg[256] = {0};
	
	while (1)
	{
		xQueueReceive(uartHandle, msg, portMAX_DELAY);
		
		if (strlen((char *)msg) > 10)
		{	
			Parse_Message((char *)msg);
		}
		
		memset(msg, 0, sizeof(msg));
	}
}

void GetTempTask(void *arg)
{
	uint8_t data[5] = {0};
	while (1)
	{
		vTaskSuspendAll();
		DHT11_Read_Data(data);
		xTaskResumeAll();
		
		xSemaphoreTake(semHandle, portMAX_DELAY);
		gInfo.humi = data[0];
		gInfo.temp = data[2];
		xSemaphoreGive(semHandle);
		
//		printf("%d %d\r\n", data[0], data[2]);
		
		osDelay(500);
	}
}

void GetLightTask(void *arg)
{
	uint8_t data[2] = {0};
	uint16_t light = 0;
	while (1)
	{
		BH1750_Send_CMD(0x20);
		
		osDelay(150);
		
		BH1750_Read_Data(data);
		
		light = BH1750_Data_To_Lx(data);
		
		xSemaphoreTake(semHandle, portMAX_DELAY);
		gInfo.light = light;
		xSemaphoreGive(semHandle);
		
		osDelay(350);
		
//		printf("%d\r\n", light);
	}
}

void OLED_Show_Task(void *arg)
{
	OLED_Show_Menu();
}

uint8_t Key_Scan(void)
{
	if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == 0)
	{
		while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == 0);
		
		return 1;
	}
	
	return 0;
}

//timer task   timeout 1s
void Data_Increase_Callback(TimerHandle_t xTimer)
{
	xSemaphoreTake(semHandle, portMAX_DELAY);
	gInfo.cur_time++;
	xSemaphoreGive(semHandle);
}

void Buzzer_Callback(TimerHandle_t xTimer)
{
	HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_8);
}

void UploadTask(void *arg)
{
	while (1)
	{
		UploadHandle();
		osDelay(500);
	}
}

/* USER CODE END Application */

